import 'dart:collection';
import 'dart:math';

/// 代码来自豆包： 我需要一个用dart写的 解析类似于python缩进代码结构到hash树的代码段
/// 用法： IndentParser().parse(code);
class IndentParser {
  static  final String sp = "    ";
  static encode(String code){
      return IndentParser().parse(code);
  }
  static decode(Map<String, dynamic> data,{sn=0, hasComment=true}){
    String rt = sn>=0? (sp * sn) + data["content"] +"\n" : "";
    var childs = data["children"] as List<dynamic>;
    for(var c in childs){
      var child = c['children'] as List<dynamic>;
      if(child.isEmpty){
          rt += (hasComment && c["comment"].isNotEmpty)
          ? "${sp * (sn+1)}${c["content"]}    //${c["comment"]}\n"
          : (sp * (sn+1)) + c["content"] +"\n";
      }else{
        rt+=decode(c,sn:sn+1,hasComment: hasComment);
      }
    }
    return rt;
  }

  static bool isNode(pData) {
    if(pData is Map){
      var map = pData as Map<String,dynamic>;
      return (map.length == 6 && map .containsKey("content"));
    }else{
      return false;
    }
  }
  // 解析代码文本，返回根节点
  Map<String, dynamic> parse(String code) {
    // 按行分割代码并去除空行
    final lines = code.split('\n')
      // .map((line) => line.trimRight())
      .where((line) => line.isNotEmpty)
      .toList();
    
    // 解析每行的缩进和内容
    final parsedLines = <_ParsedLine>[];
    for (var i = 0; i < lines.length; i++) {
      final line = lines[i];
      final indent = _calculateIndent(line);
      final content = line.substring(indent);
      parsedLines.add(_ParsedLine(indent, content, i));
    }
    
    // 构建哈希树
    return _buildTree(parsedLines);
  }
  
  // 计算行的缩进空格数
  int _calculateIndent(String line) {
    int indent = 0;
    while (indent < line.length && line[indent] == ' ') {
      indent++;
    }
    return indent;
  }
  
  // 构建哈希树
  Map<String, dynamic> _buildTree(List<_ParsedLine> lines) {
    if (lines.isEmpty) return {'children': []};
    var lineFirst = "";
    if(lines.first.comment.isNotEmpty){
      lineFirst = lines.removeAt(0).comment;
    }
    // 创建根节点
    final root = <String, dynamic>{
      'content': 'root',
      'comment': lineFirst,
      'depth' : 0,
      'level': -1,
      'line': -1,
      'children': [],
    };
    
    // 使用栈来跟踪当前层级
    final stack = Queue<Map<String, dynamic>>();
    stack.add(root);
    
    for (var line in lines) {
      // 找到正确的父级
      while (stack.isNotEmpty && stack.last['level'] >= line.indent) {
        stack.removeLast();
      }
      // 创建新节点
      final node = <String, dynamic>{
        'content': line.content,  
        'comment': line.comment,
        'depth' :stack.last['depth']+1,
        'level': line.indent,
        'line': line.lineNumber,
        'children': [],
      };
      
      // 将节点添加到父级的子节点列表
      stack.last['children'].add(node);
      stack.add(node);
    }
    
    return root;
  }

 
}

// 内部类，表示解析后的行
class _ParsedLine {
  final int indent;
  String content;
  String comment="";
  final int lineNumber;
  
  _ParsedLine(this.indent, this.content, this.lineNumber){
    if(content.contains("#") || content.contains("//")){
        var a = content.split(RegExp(r"#|//"));
        if(!a.first.endsWith('\\') && !a.first.endsWith(':')){
          content = "${a.first.trimRight()}\n";
          comment = a.last.trimRight();
        }
    }
  }
  
  @override
  String toString() => '[$lineNumber] ${' ' * indent}$content';
}

class IndentElement {
  String content;
  String comment="";
  int depth=0;
  List<dynamic> children;
  IndentElement.simple(this.content)
    :children=[];
     
  IndentElement(Map<String, dynamic> item) 
      : content = item["content"],
        depth = item.containsKey("depth") ?  item["depth"] : 0,
        comment = item.containsKey("comment") ?  item["comment"] : "",
        children = item["children"] ?? []; // 直接初始化字段

  Map<String, dynamic> toData(){
      return {
        'content': content,
        'comment': comment,
        'depth': depth,
        'level': 0,
        'line': 0,
        'children': children,
      };
  }
  static void forEach(v,Function (IndentElement p) run){
       final children = v["children"];
       for(var p in children){
        if(p["children"].isNotEmpty){
            forEach(p,run);
        }
        run(IndentElement(p));
      }
  }
  //叶子节点运行
  static leafRun(List<dynamic> children,Function(IndentElement p) run) {
      for(var p in children){
        if(p["children"].isNotEmpty){
            leafRun(p["children"],run);
        }else{
          run(IndentElement(p));
        }
      }
  }

  //相同深度
  static sameDepth(List<dynamic> children,Function(IndentElement p) run) {
      var nextDepth = true;
      for(var p in children){
        if(p["content"].isNotEmpty && p["children"].isEmpty){
          run(IndentElement(p));
          nextDepth = false;
          break;
        }
      }
      if(!nextDepth) return; 
      children
        .where((p) => p["children"].isNotEmpty)
        .forEach((p) => sameDepth(p["children"], run));
  }
  int get minDepth{
    var rt=0;
    leafRun(children,(p) {
        rt =(rt==0) ? p.depth-depth: min(rt,p.depth-depth);
    });
    return rt;
  }

  int get maxDepth{
    var rt=0;
    sameDepth(children,(p) {
        rt = max(rt,p.depth-depth);
    });
    return rt;
  }
}